package arch.service.impl.user;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import arch.dao.user.ModuleDao;
import arch.domain.user.Module;
import arch.domain.user.Privilege;
import arch.domain.user.Role;
import arch.domain.user.Privilege.Type;
import arch.service.user.ModuleService;
import arch.service.user.PrivilegeService;
import arch.util.UUID;
/**
 * 
 * @author ZhaoWangLong Sep 7, 2012
 *
 */
@Service("moduleService")
@Transactional
public class ModuleServiceBean implements ModuleService {
	@Resource private ModuleDao moduleDao;
	@Resource private PrivilegeService privilegeService;
	private final Logger logger = Logger.getLogger(ModuleServiceBean.class);
	
	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public Module find(Module module, boolean parent) {
		StringBuffer sql = new StringBuffer();
		if(parent){
			sql.append("select a.MODULE_ID, a.MODULE_NAME, a.INDEX, a.PMODULE, ")
				.append(" b.MODULE_NAME as PMODULE_NAME,b.INDEX as PMODULE_INDEX,")
				.append(" b.ACTION_URL as PMODULE_ACTION_URL,b.IMAGE_URL as PMODULE_IMAGE_URL,")
				.append(" a.ACTION_URL,a.IMAGE_URL, a.DESCRIPTION, a.CREATE_TIME, a.LAST_UPDATE_TIME ")
				.append(" from ID_MODULE as a inner join ID_MODULE as b  ")
				.append(" on (a.PMODULE = b.MODULE_ID) where a.MODULE_ID = ? ");
			
			List<Module> modules = this.moduleDao.queryList(sql.toString(), true, module.getModuleId());
			if(modules!=null && modules.size()>0)
				return modules.get(0);
			return null;
		}else
			return find(module);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Module> findAll() {
		StringBuffer sql = new StringBuffer();
		sql.append("select MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL, ")
			.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME ")
			.append(" from ID_MODULE  ");
		
		logger.debug("SQL > "+sql.toString());
		return this.moduleDao.queryList(sql.toString(), false);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Module> findChildren(Module current, boolean isAll) {
		StringBuffer sql = new StringBuffer();
		if(isAll){
			sql.append("with children(MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL, ")
				.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME) as ( ")
				.append("  select MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL,  ")
				.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME ")
				.append(" from ID_MODULE where MODULE_ID = ?  ")
				.append(" union all ")
				.append(" select a.MODULE_ID, a.MODULE_NAME, a.INDEX, a.PMODULE, a.ACTION_URL,  ")
				.append("a.IMAGE_URL, a.DESCRIPTION, a.CREATE_TIME, a.LAST_UPDATE_TIME ")
				.append(" from ID_MODULE as a ,children as b where a.PMODULE = b.MODULE_ID ")
				.append(")select MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL, ")
				.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME from children ")
				.append(" order by INDEX asc");
		}else{
			sql.append("  select MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL,  ")
				.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME ")
				.append(" from ID_MODULE where PMODULE = ? or MODULE_ID = '")
				.append(current.getModuleId()).append("' order by INDEX asc ");
		}
		logger.debug("SQL > "+sql.toString() );
		
		return this.moduleDao.queryList(sql.toString(), false, current.getModuleId());
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	private Integer findMaxIndex(){
		String sql = "select max(INDEX) from ID_MODULE ";
		
		return this.moduleDao.queryInt(sql);
	}
	
	public void add(Module entity) {
		String moduleId = UUID.id("ID", "ME");
		Timestamp createTime = new Timestamp(new Date().getTime());
		
		entity.setModuleId(moduleId);
		entity.setIndex(findMaxIndex()+1);
		entity.setCreateTime(createTime);
		entity.setLastUpdateTime(createTime);

		this.moduleDao.persist(entity);
		
		Privilege privilege = new Privilege();
		privilege.setType(Type.MODULE);
		privilege.setResourceId(moduleId);
		this.privilegeService.add(privilege);
	}

	public void delete(Module primaryKey) {
		this.moduleDao.remove(primaryKey.getModuleId());
		
		Privilege privilege = new Privilege();
		privilege.setType(Type.MODULE);
		privilege.setResourceId(primaryKey.getModuleId());
		this.privilegeService.delete(privilege);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public Module find(Module primaryKey) {
		return this.moduleDao.find(primaryKey.getModuleId());
	}

	public void update(Module entity) {
		Timestamp lastUpdateTime = new Timestamp(new Date().getTime());
		entity.setLastUpdateTime(lastUpdateTime);
		
		this.moduleDao.merge(entity);
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Module> findList(Role role) {
		StringBuffer sql = new StringBuffer();
		sql.append(" select MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL, ")
		.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME  ")
		.append(" from ID_MODULE where MODULE_ID in ( ")
		.append(" select RESOURCE_ID from ID_PRIVILEGE where TYPE = ? and ID in ( ")
		.append(" select PRIVILEGE_ID from ID_ROLE_PRIVILEGE where ROLE_ID = ? )) order by INDEX asc ");

		logger.debug("SQL > "+sql.toString());
		return this.moduleDao.queryList(sql.toString(), false, "MODULE",role.getRoleId());
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public List<Module> findList() {
		StringBuffer sql = new StringBuffer();
		sql.append(" select MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL, ")
		.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME  ")
		.append(" from ID_MODULE where MODULE_ID in ( ")
		.append(" select RESOURCE_ID from ID_PRIVILEGE where TYPE = ? ) order by INDEX asc ");

		logger.debug("SQL > "+sql.toString());
		return this.moduleDao.queryList(sql.toString(), false, "MODULE");
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	public Module find(Privilege privilege) {
		StringBuffer sql = new StringBuffer();
		sql.append(" select MODULE_ID, MODULE_NAME, INDEX, PMODULE, ACTION_URL, ")
		.append(" IMAGE_URL, DESCRIPTION, CREATE_TIME, LAST_UPDATE_TIME  ")
		.append(" from ID_MODULE where MODULE_ID = ( ") 
		.append(" select RESOURCE_ID from ID_PRIVILEGE where ID = ? )");
		
		logger.debug("SQL > "+sql.toString());
		List<Module> modules = this.moduleDao.queryList(sql.toString(), false, privilege.getId());
		
		if(modules!=null && modules.size()>0)
			return modules.get(0);
		return null;
	}

}
